package com.gitee.qdbp.vmall.web.controller.sales.usr.goods;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.model.paging.PageList;
import com.gitee.qdbp.able.result.ResponseMessage;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.able.utils.VerifyTools;
import com.gitee.qdbp.base.annotation.OperateRecord;
import com.gitee.qdbp.base.enums.OperateType;
import com.gitee.qdbp.base.model.condition.OrderPaging;
import com.gitee.qdbp.base.system.model.IAccount;
import com.gitee.qdbp.base.utils.SessionTools;
import com.gitee.qdbp.general.common.enums.VersionState;
import com.gitee.qdbp.vmall.sales.api.goods.main.model.GoodsVersionBean;
import com.gitee.qdbp.vmall.sales.api.goods.main.model.GoodsVersionWhere;
import com.gitee.qdbp.vmall.sales.api.goods.main.service.IGoodsVersionQueryer;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.InventoryRealtimeBean;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.ShoppingCartBean;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.ShoppingCartWhere;
import com.gitee.qdbp.vmall.sales.api.goods.manage.model.ShoppingGoodsItem;
import com.gitee.qdbp.vmall.sales.api.goods.manage.service.IInventoryRealtimeQueryer;
import com.gitee.qdbp.vmall.sales.api.goods.manage.service.IShoppingCartExecutor;
import com.gitee.qdbp.vmall.sales.api.goods.manage.service.IShoppingCartQueryer;
import com.gitee.qdbp.vmall.sales.api.order.main.model.CreateGoodsOrderParams;
import com.gitee.qdbp.vmall.sales.api.order.main.model.OrderReceiverBase;
import com.gitee.qdbp.vmall.sales.api.order.main.service.IGoodsOrderExecutor;
import com.gitee.qdbp.vmall.sales.api.specific.model.SkuInstance;
import com.gitee.qdbp.vmall.web.controller.sales.usr.goods.model.ShoppingCartItemDetails;

/**
 * 页面跳转控制器
 *
 * @author zhaohuihua
 * @version 180706
 */
@Controller
@RequestMapping("actions/goods")
@OperateRecord(enable = false)
public class GoodsManageController {

    @Autowired
    private IGoodsVersionQueryer goodsVersionQueryer;
    @Autowired
    private IShoppingCartQueryer shoppingCartQueryer;
    @Autowired
    private IShoppingCartExecutor shoppingCartExecutor;
    @Autowired
    private IInventoryRealtimeQueryer inventoryRealtimeQueryer;
    @Autowired
    private IGoodsOrderExecutor goodsOrderExecutor;

    /** 商品详情 **/
    @ResponseBody
    @RequestMapping("details")
    @OperateRecord(value = "商品:详情", type = OperateType.QUERY)
    public ResponseMessage queryGoodsDetails(String uid) {
        SecurityUtils.getSubject().isPermitted("*");

        try {
            GoodsVersionBean bean = goodsVersionQueryer.findByUid(uid);
            if (bean == null) {
                return new ResponseMessage(ResultCode.RECORD_NOT_EXIST);
            } else {
                return new ResponseMessage(bean);
            }
        } catch (ServiceException e) {
            return new ResponseMessage(e);
        }
    }

    /** 创建订单 **/
    @ResponseBody
    @RequestMapping("order/create")
    @OperateRecord(value = "商品:创建订单", type = OperateType.CREATE)
    public ResponseMessage createOrder(CreateGoodsOrderParams params, OrderReceiverBase receiver) {
        try {
            IAccount me = SessionTools.getLoginUser();
            String orderId = goodsOrderExecutor.create(me.getId(), params, receiver, me);
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", orderId);
            return new ResponseMessage(map);
        } catch (ServiceException e) {
            return new ResponseMessage(e);
        }
    }

    /** 加入购物车 **/
    @ResponseBody
    @RequestMapping("shopping-cart/add")
    @OperateRecord(value = "购物车:新增", type = OperateType.CREATE)
    public ResponseMessage addToShoppingCart(ShoppingGoodsItem item) {
        try {
            IAccount me = SessionTools.getLoginUser();
            shoppingCartExecutor.create(me.getId(), item, me);
            return new ResponseMessage();
        } catch (ServiceException e) {
            return new ResponseMessage(e);
        }
    }

    /** 修改购物车内商品的数量 **/
    @ResponseBody
    @RequestMapping("shopping-cart/update-quantity")
    @OperateRecord(value = "购物车:修改数量", type = OperateType.UPDATE)
    public ResponseMessage updateShoppingQuantity(String shoppingCartId, int quantity) {
        try {
            IAccount me = SessionTools.getLoginUser();
            shoppingCartExecutor.updateQuantityById(shoppingCartId, quantity, me);
            return new ResponseMessage();
        } catch (ServiceException e) {
            return new ResponseMessage(e);
        }
    }

    /** 修改购物车内商品的选中状态, shoppingCartId=*表示修改当前用户所有记录 **/
    @ResponseBody
    @RequestMapping("shopping-cart/update-checked")
    @OperateRecord(value = "购物车:修改选中状态", type = OperateType.UPDATE)
    public ResponseMessage updateShoppingChecked(String shoppingCartId, boolean checked) {
        try {
            IAccount me = SessionTools.getLoginUser();
            if ("*".equals(shoppingCartId)) {
                shoppingCartExecutor.updateCheckedByUser(me.getId(), checked, me);
            } else {
                shoppingCartExecutor.updateCheckedById(shoppingCartId, checked, me);
            }
            return new ResponseMessage();
        } catch (ServiceException e) {
            return new ResponseMessage(e);
        }
    }

    /** 删除购物车内的商品 **/
    @ResponseBody
    @RequestMapping("shopping-cart/delete")
    @OperateRecord(value = "购物车:删除", type = OperateType.DELETE)
    public ResponseMessage delete(String shoppingCartId) {
        try {
            IAccount me = SessionTools.getLoginUser();
            shoppingCartExecutor.deleteById(shoppingCartId, me);
            return new ResponseMessage();
        } catch (ServiceException e) {
            return new ResponseMessage(e);
        }
    }

    /** 查询购物车 **/
    @ResponseBody
    @RequestMapping("shopping-cart/list")
    @OperateRecord(value = "购物车:查询", type = OperateType.QUERY)
    public ResponseMessage listShoppingCart(ShoppingCartWhere where, OrderPaging paging) {
        try {
            IAccount me = SessionTools.getLoginUser();
            where.setUserId(me.getId());
            PageList<ShoppingCartItemDetails> list = listShoppingCartItems(where, paging);
            return new ResponseMessage(list);
        } catch (ServiceException e) {
            return new ResponseMessage(e);
        }
    }

    private PageList<ShoppingCartItemDetails> listShoppingCartItems(ShoppingCartWhere where,
            OrderPaging paging) throws ServiceException {
        PageList<ShoppingCartBean> items;
        { // 查询订单明细
            items = shoppingCartQueryer.list(where, paging);
        }
        if (items.isEmpty()) {
            return PageList.of(new ArrayList<>());
        }

        Map<String, GoodsVersionBean> oldGoodses = new HashMap<>();
        Set<String> goodsUids = new HashSet<>();
        { // 查询原商品详情
            Set<String> goodsVids = new HashSet<>();
            for (ShoppingCartBean item : items) {
                goodsVids.add(item.getGoodsVid());
            }
            GoodsVersionWhere w = new GoodsVersionWhere();
            w.setVids(new ArrayList<>(goodsVids));
            PageList<GoodsVersionBean> temp = goodsVersionQueryer.list(w, OrderPaging.NONE);
            for (GoodsVersionBean goods : temp) {
                oldGoodses.put(goods.getVid(), goods);
                goodsUids.add(goods.getUid());
            }
        }
        Map<String, GoodsVersionBean> newGoodses = new HashMap<>();
        { // 查询最新版本的商品详情
            GoodsVersionWhere w = new GoodsVersionWhere();
            w.setUids(new ArrayList<>(goodsUids));
            w.setVersionState(VersionState.ACTIVATED);
            PageList<GoodsVersionBean> temp = goodsVersionQueryer.list(w, OrderPaging.NONE);
            for (GoodsVersionBean goods : temp) {
                newGoodses.put(goods.getUid(), goods);
            }
        }
        Map<String, InventoryRealtimeBean> inventories = new HashMap<>();
        { // 查询实时库存
            Set<String> skuIds = new HashSet<>();
            for (ShoppingCartBean item : items) {
                skuIds.add(item.getSkuId());
            }
            List<InventoryRealtimeBean> temp = inventoryRealtimeQueryer.listBySkuId(new ArrayList<>(skuIds));
            for (InventoryRealtimeBean bean : temp) {
                inventories.put(bean.getSkuId(), bean);
            }
        }

        // 组合
        List<ShoppingCartItemDetails> result = ShoppingCartBean.to(items.toList(), ShoppingCartItemDetails.class);
        for (ShoppingCartItemDetails item : result) {
            GoodsVersionBean oldGoods = oldGoodses.get(item.getGoodsVid());
            if (oldGoods == null) continue;
            GoodsVersionBean newGoods = newGoodses.get(oldGoods.getUid());
            if (newGoods == null) newGoods = oldGoods;
            SkuInstance oldSku = findSkuInstance(oldGoods, item.getSkuId());
            SkuInstance newSku = findSkuInstance(newGoods, item.getSkuId());
            double oldPrice = oldSku == null ? oldGoods.getPriceValue() : oldSku.getPriceValue();
            double newPrice = newSku == null ? newGoods.getPriceValue() : newSku.getPriceValue();

            // 设置商品信息
            item.setGoods(newGoods);
            item.setSku(newSku);
            item.setPriceChange(newPrice - oldPrice);

            InventoryRealtimeBean inventoriy = inventories.get(item.getSkuId());
            if (inventoriy != null) {
                item.setStockQuantity(inventoriy.getStockQuantity());
                item.setSoldQuantity(inventoriy.getSoldQuantity());
            }
        }

        return PageList.of(result);
    }

    private static SkuInstance findSkuInstance(GoodsVersionBean goods, String skuId) {
        List<SkuInstance> skuData = goods.getSkuInstanceData();
        if (VerifyTools.isNoneBlank(skuId, skuData)) {
            for (SkuInstance sku : skuData) {
                if (skuId.equals(sku.getId())) {
                    return sku;
                }
            }
        }
        return null;
    }
}
